﻿using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

namespace ToolUtil
{
    public class ProcessWriteData
    {
        private Semaphore x_Write;  //可写的信号
        private Semaphore x_Read;   //可读的信号
        private IntPtr x_handle;    //文件句柄
        private IntPtr x_addr;      //共享内存地址
        uint mapLength;             //共享内存长

        #region 内存操作的函数

        const int INVALID_HANDLE_VALUE = -1;
        const int PAGE_READWRITE = 0x04;
        const int FILE_MAP_ALL_ACCESS = 0x0002;
        const int FILE_MAP_WRITE = 0x0002;

        [DllImport("User32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
        [DllImport("User32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        //共享内存
        [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")]
        private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile,
         UInt32 lpAttributes,                                        //LPSECURITY_ATTRIBUTES lpAttributes,  //0
         UInt32 flProtect,                                           //DWORD flProtect
         UInt32 dwMaximumSizeHigh,                                   //DWORD dwMaximumSizeHigh,
         UInt32 dwMaximumSizeLow,                                    //DWORD dwMaximumSizeLow,
         string lpName                                               //LPCTSTR lpName
         );

        [DllImport("Kernel32.dll", EntryPoint = "OpenFileMapping")]
        private static extern IntPtr OpenFileMapping(
         UInt32 dwDesiredAccess,        //DWORD dwDesiredAccess,
         int bInheritHandle,            //BOOL bInheritHandle,
         string lpName                  //LPCTSTR lpName
         );


        [DllImport("Kernel32.dll", EntryPoint = "MapViewOfFile")]
        private static extern IntPtr MapViewOfFile(
         IntPtr hFileMappingObject,     //HANDLE hFileMappingObject,
         UInt32 dwDesiredAccess,        //DWORD dwDesiredAccess
         UInt32 dwFileOffsetHight,      //DWORD dwFileOffsetHigh,
         UInt32 dwFileOffsetLow,        //DWORD dwFileOffsetLow,
         UInt32 dwNumberOfBytesToMap    //SIZE_T dwNumberOfBytesToMap
         );

        [DllImport("Kernel32.dll", EntryPoint = "UnmapViewOfFile")]
        private static extern int UnmapViewOfFile(IntPtr lpBaseAddress);

        [DllImport("Kernel32.dll", EntryPoint = "CloseHandle")]
        private static extern int CloseHandle(IntPtr hObject);

        #endregion
        public ProcessWriteData()
        {
            mapLength = 1024;
        }
        #region 向进程共享内存中写入数据（B模式运行的进程）

        /// <summary>
        /// B进程：向共享内存中写入的数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void WriteData2SharedMemory(string readedBuffer, string ex)
        {
            byte[] sendStr;
            try
            {
                x_Write = Semaphore.OpenExisting("SerGdlis");
                x_Read = Semaphore.OpenExisting("GdlisNet");
                x_handle = OpenFileMapping(FILE_MAP_WRITE, 0, "shareSerGdlis");
                x_addr = MapViewOfFile(x_handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
                Console.WriteLine("B Process Memory Address Operating:" + x_addr);
                // 等待写的信号量
                if (x_Write.WaitOne())
                {
                    if (!string.IsNullOrEmpty(ex))
                    {
                        x_Write.Release();
                    }
                    sendStr = Encoding.Default.GetBytes(readedBuffer + '\0');//如果要是超长的话，应另外处理，最好是分配足够的内存
                    if (sendStr.Length < mapLength)
                        CopyByte2Memory(sendStr, x_addr);

                    x_Read.Release();
                }
                else
                    x_Write.Release();
            }
            catch (WaitHandleCannotBeOpenedException)
            {
                Console.WriteLine("不存在系统信号量!");
                return;
            }
        }


        static unsafe void CopyByte2Memory(byte[] byteSrc, IntPtr dst)
        {
            fixed (byte* pSrc = byteSrc)
            {
                byte* pDst = (byte*)dst;
                byte* psrc = pSrc;
                for (int i = 0; i < byteSrc.Length; i++)
                {
                    *pDst = *psrc;
                    pDst++;
                    psrc++;
                }
            }
        }
        #endregion
    }
}
